#include "ipc.h"


int first_time=1;
Array* chanels=NULL;
int my_fds[2];

typedef struct {
	int pid;
	int fd;
} chanel_t;


int ipc_open(char * filepath,char* argv[]){
	if(first_time){
		chanels=newArray();
		first_time=0;

		pipe(my_fds);
	}

	int new_pipe[2];

	chanel_t* chanel=malloc(sizeof(chanel_t));

	pipe(new_pipe);
	
	switch(chanel->pid=fork()){
		case -1:
			printf("error");
			exit(-21);
		case 0:
			close(new_pipe[1]);
			close(my_fds[0]);
			if(new_pipe[0]!=3){
				dup2(new_pipe[0],3);
				close(new_pipe[0]);
			}
			if(my_fds[1]!=4){
				dup2(my_fds[1],4);
				close(my_fds[1]);
			}
			execve(filepath, argv,NULL);
		default:
			chanel->fd=new_pipe[1];
			close(new_pipe[0]);
			add(chanels,chanel);
	}
		
	return chanel->pid;
}

int has_pid(void* chanel, void* pid){
	return ((chanel_t*)chanel)->pid==*((int*)pid);
}

int ipc_msg_recive(int from, message_t* message){
	
	int fd= from==SERVER? 3 : my_fds[0];
	int pid;
	if(read(fd,&pid,sizeof(int))<=0) return -2;
	pid= chanels==NULL? SERVER : pid;

	int msg_size;
	if(read(fd,(char*)&msg_size,sizeof(int))<=0) return -2;

	char * text=malloc(msg_size);//FREE
	if(read(fd,text,msg_size)<=0) return -2;

	message->size=msg_size;
	message->text=text;
	return pid;

}

int ipc_msg_send(int pid, message_t* message){
	char* plaintext=malloc(2*sizeof(int)+message->size);
	char* plaintextp=plaintext;

	*((int*)plaintextp)= pid==SERVER? getpid() : SERVER;
	plaintextp+=sizeof(int);

	*((int*)plaintextp)=message->size;
	plaintextp+=sizeof(int);

	memcpy(plaintextp,message->text,message->size);
	
	int fd= pid==SERVER? 4 : ((chanel_t*)getElementByIndex( chanels, 
					getIndexByFunction(chanels,has_pid,&pid) ))->fd;

	int writen=write(fd,plaintext,2*sizeof(int)+message->size);
	free(plaintext);
	return -(writen<0);

}

void ipc_close(){
	if(!first_time){
		close(my_fds[0]);
		close(my_fds[1]);
		
		if(chanels){
			int i;
			for(i=0;i<chanels->count;i++){
				free(chanels->array[i]);
			}
			deleteArray(chanels);
		}
	}
}
